Completed
Pull Request — master (#328)
by
unknown
02:43
created

View.elementToFile   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
/**
2
 * Nextcloud - Gallery
3
 *
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Olivier Paroz <[email protected]>
9
 *
10
 * @copyright Olivier Paroz 2017
11
 */
12
/* global Handlebars, Gallery, Thumbnails */
13
(function ($, _, OC, t, Gallery) {
14
	"use strict";
15
16
	var TEMPLATE_ADDBUTTON = '<a href="#" class="button new"><span class="icon icon-add"></span><span class="hidden-visually">New</span></a>';
0 ignored issues
show
Coding Style introduced by
Line is too long.
Loading history...
17
	var TEMPLATE_DOWNLOADBUTTON = '<span id="selectedActionsList" class="selectedActions hidden"><a href="#" class="button download"><span class="icon icon-download"></span><span class="hidden-visually">Download</span></a></span>';
0 ignored issues
show
Coding Style introduced by
Line is too long.
Loading history...
18
19
	/**
20
	 * Builds and updates the Gallery view
21
	 *
22
	 * @constructor
23
	 */
24
	var View = function () {
25
		this.element = $('#gallery');
26
		this.loadVisibleRows.loading = false;
27
		this._setupUploader();
28
		this.breadcrumb = new Gallery.Breadcrumb();
29
		this.emptyContentElement = $('#emptycontent');
30
		this.controlsElement = $('#controls');
31
	};
32
33
	View.prototype = {
34
		element: null,
35
		breadcrumb: null,
36
		requestId: -1,
37
		emptyContentElement: null,
38
		controlsElement: null,
39
		/**
40
		 * Map of file id to file data
41
		 * @type Object.<int, Object>
42
		 */
43
		_selectedFiles: {},
44
		/**
45
		 * Summary of selected files.
46
		 * @type OCA.Files.FileSummary
47
		 */
48
		_selectionSummary: null,
49
		/**
50
		 * @type Backbone.Model
51
		 */
52
		_filesConfig: undefined,
53
		/**
54
		 * Initialiation status
55
		 * @type Boolean
56
		 */
57
		_initialized: false,
58
59
		/**
60
		 * Removes all thumbnails from the view
61
		 */
62
		clear: function () {
63
			this.loadVisibleRows.processing = false;
64
			this.loadVisibleRows.loading = null;
65
			// We want to keep all the events
66
			this.element.children().detach();
67
			this.showLoading();
68
		},
69
70
		/**
71
		 * @param {string} path
72
		 * @returns {boolean}
73
		 */
74
		_isValidPath: function(path) {
75
			var sections = path.split('/');
76
			for (var i = 0; i < sections.length; i++) {
77
				if (sections[i] === '..') {
78
					return false;
79
				}
80
			}
81
82
			return path.toLowerCase().indexOf(decodeURI('%0a')) === -1 &&
83
				path.toLowerCase().indexOf(decodeURI('%00')) === -1;
84
		},
85
86
		/**
87
		 * Populates the view if there are images or albums to show
88
		 *
89
		 * @param {string} albumPath
90
		 * @param {string|undefined} errorMessage
91
		 */
92
		init: function (albumPath, errorMessage) {
93
			// Set path to an empty value if not a valid one
94
			if(!this._isValidPath(albumPath)) {
95
				albumPath = '';
96
			}
97
98
			// Only do it when the app is initialised
99
			if (this.requestId === -1) {
100
				this._initButtons();
101
				this._blankUrl();
102
			}
103
			if ($.isEmptyObject(Gallery.imageMap)) {
104
				Gallery.view.showEmptyFolder(albumPath, errorMessage);
105
			} else {
106
				this.viewAlbum(albumPath);
107
			}
108
109
			this._setBackgroundColour();
110
111
			this._initSelection();
112
			this.initialized = true;
113
		},
114
115
		/**
116
		 * Starts the slideshow
117
		 *
118
		 * @param {string} path
119
		 * @param {string} albumPath
120
		 */
121
		startSlideshow: function (path, albumPath) {
122
			var album = Gallery.albumMap[albumPath];
123
			var images = album.images;
124
			var startImage = Gallery.imageMap[path];
125
			Gallery.slideShow(images, startImage, false);
126
		},
127
128
		/**
129
		 * Sets up the controls and starts loading the gallery rows
130
		 *
131
		 * @param {string|null} albumPath
132
		 */
133
		viewAlbum: function (albumPath) {
134
			albumPath = albumPath || '';
135
			if (!Gallery.albumMap[albumPath]) {
136
				return;
137
			}
138
139
			this.clear();
140
141
			if (albumPath !== Gallery.currentAlbum
142
				|| (albumPath === Gallery.currentAlbum &&
143
				Gallery.albumMap[albumPath].etag !== Gallery.currentEtag)) {
144
				Gallery.currentAlbum = albumPath;
145
				Gallery.currentEtag = Gallery.albumMap[albumPath].etag;
146
				this._setupButtons(albumPath);
147
			}
148
149
			Gallery.albumMap[albumPath].viewedItems = 0;
150
			Gallery.albumMap[albumPath].preloadOffset = 0;
151
152
			// Each request has a unique ID, so that we can track which request a row belongs to
153
			this.requestId = Math.random();
154
			Gallery.albumMap[Gallery.currentAlbum].requestId = this.requestId;
155
156
			// Loading rows without blocking the execution of the rest of the script
157
			setTimeout(function () {
158
				this.loadVisibleRows.activeIndex = 0;
159
				this.loadVisibleRows(Gallery.albumMap[Gallery.currentAlbum]);
160
			}.bind(this), 0);
161
		},
162
163
		/**
164
		 * Manages the sorting interface
165
		 *
166
		 * @param {string} sortType name or date
167
		 * @param {string} sortOrder asc or des
168
		 */
169
		sortControlsSetup: function (sortType, sortOrder) {
170
			var reverseSortType = 'date';
171
			if (sortType === 'date') {
172
				reverseSortType = 'name';
173
			}
174
			this._setSortButton(sortType, sortOrder, true);
175
			this._setSortButton(reverseSortType, 'asc', false); // default icon
176
		},
177
178
		/**
179
		 * Loads and displays gallery rows on screen
180
		 *
181
		 * view.loadVisibleRows.loading holds the Promise of a row
182
		 *
183
		 * @param {Album} album
184
		 */
185
		loadVisibleRows: function (album) {
186
			var view = this;
187
			// Wait for the previous request to be completed
188
			if (this.loadVisibleRows.processing) {
189
				return;
190
			}
191
192
			/**
193
			 * At this stage, there is no loading taking place, so we can look for new rows
194
			 */
195
196
			var scroll = $('#content-wrapper').scrollTop() + $(window).scrollTop();
197
			// 2 windows worth of rows is the limit from which we need to start loading new rows.
198
			// As we scroll down, it grows
199
			var targetHeight = ($(window).height() * 2) + scroll;
200
			// We throttle rows in order to try and not generate too many CSS resizing events at
201
			// the same time
202
			var showRows = _.throttle(function (album) {
203
204
				// If we've reached the end of the album, we kill the loader
205
				if (!(album.viewedItems < album.subAlbums.length + album.images.length)) {
0 ignored issues
show
Coding Style introduced by
The usage of ! looks confusing here.

The following shows a case which JSHint considers confusing and its respective non-confusing counterpart:

! (str.indexOf(i) > -1) // Bad
str.indexOf(i) === -1 // Good
Loading history...
206
					view.loadVisibleRows.processing = false;
207
					view.loadVisibleRows.loading = null;
208
					return;
209
				}
210
211
				// Prevents creating rows which are no longer required. I.e when changing album
212
				if (view.requestId !== album.requestId) {
213
					return;
214
				}
215
216
				// We can now safely create a new row
217
				var row = album.getRow($(window).width());
218
				var rowDom = row.getDom();
219
				view.element.append(rowDom);
220
221
				return album.fillNextRow(row).then(function () {
222
					if (album.viewedItems < album.subAlbums.length + album.images.length &&
223
						view.element.height() < targetHeight) {
224
						return showRows(album);
225
					}
226
					// No more rows to load at the moment
227
					view.loadVisibleRows.processing = false;
228
					view.loadVisibleRows.loading = null;
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
229
				}, function () {
230
					// Something went wrong, so kill the loader
231
					view.loadVisibleRows.processing = false;
232
					view.loadVisibleRows.loading = null;
233
				});
234
			}, 100);
235
			if (this.element.height() < targetHeight) {
236
				this._showNormal();
237
				this.loadVisibleRows.processing = true;
238
				album.requestId = view.requestId;
239
				this.loadVisibleRows.loading = showRows(album);
240
			}
241
		},
242
243
		/**
244
		 * Shows an empty gallery message
245
		 *
246
		 * @param {string} albumPath
247
		 * @param {string|null} errorMessage
248
		 */
249
		showEmptyFolder: function (albumPath, errorMessage) {
250
			var message = '<div class="icon-gallery"></div>';
251
			var uploadAllowed = true;
252
253
			this.element.children().detach();
254
			this.removeLoading();
255
256
			if (!_.isUndefined(errorMessage) && errorMessage !== null) {
257
				message += '<h2>' + t('gallery',
258
						'Album cannot be shown') + '</h2>';
259
				message += '<p>' + escapeHTML(errorMessage) + '</p>';
0 ignored issues
show
Bug introduced by
escapeHTML does not seem to be defined.
Loading history...
260
				uploadAllowed = false;
261
			} else {
262
				message += '<h2>' + t('gallery',
263
						'No media files found') + '</h2>';
264
				// We can't upload yet on the public side
265
				if (Gallery.token) {
266
					message += '<p>' + t('gallery',
267
							'Upload pictures in the Files app to display them here') + '</p>';
268
				} else {
269
					message += '<p>' + t('gallery',
270
							'Upload new files via drag and drop or by using the [+] button above') +
271
						'</p>';
272
				}
273
			}
274
			this.emptyContentElement.html(message);
275
			this.emptyContentElement.removeClass('hidden');
276
277
			this._hideButtons(uploadAllowed);
278
			Gallery.currentAlbum = albumPath;
279
			var availableWidth = $(window).width() - Gallery.buttonsWidth;
280
			this.breadcrumb.init(albumPath, availableWidth);
281
			Gallery.config.albumDesign = null;
282
		},
283
284
		/**
285
		 * Dims the controls bar when retrieving new content. Matches the effect in Files
286
		 */
287
		dimControls: function () {
288
			// Use the existing mask if its already there
289
			var $mask = this.controlsElement.find('.mask');
290
			if ($mask.exists()) {
291
				return;
292
			}
293
			$mask = $('<div class="mask transparent"></div>');
294
			this.controlsElement.append($mask);
295
			$mask.removeClass('transparent');
296
		},
297
298
		/**
299
		 * Shows the infamous loading spinner
300
		 */
301
		showLoading: function () {
302
			this.emptyContentElement.addClass('hidden');
303
			this.controlsElement.removeClass('hidden');
304
			$('#content').addClass('icon-loading');
305
			this.dimControls();
306
		},
307
308
		/**
309
		 * Removes the spinner in the main area and restore normal visibility of the controls bar
310
		 */
311
		removeLoading: function () {
312
			$('#content').removeClass('icon-loading');
313
			this.controlsElement.find('.mask').remove();
314
		},
315
316
		/**
317
		 * Shows thumbnails
318
		 */
319
		_showNormal: function () {
320
			this.emptyContentElement.addClass('hidden');
321
			this.controlsElement.removeClass('hidden');
322
			this.removeLoading();
323
		},
324
325
		/**
326
		 * Sets up our custom handlers for folder uploading operations
327
		 *
328
		 * @see OC.Upload.init/file_upload_param.done()
329
		 *
330
		 * @private
331
		 */
332
		_setupUploader: function () {
333
			var $uploadEl = $('#file_upload_start');
334
			if (!$uploadEl.exists()) {
335
				return;
336
			}
337
			this._uploader = new OC.Uploader($uploadEl, {
338
				fileList: FileList,
0 ignored issues
show
Bug introduced by
The variable FileList seems to be never declared. If this is a global, consider adding a /** global: FileList */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
339
				dropZone: $('#content')
340
			});
341
			this._uploader.on('add', function (e, data) {
342
				data.targetDir = '/' + Gallery.currentAlbum;
343
			});
344
			this._uploader.on('done', function (e, upload) {
345
				var data = upload.data;
346
347
				// is that the last upload ?
348
				if (data.files[0] === data.originalFiles[data.originalFiles.length - 1]) {
349
					var fileList = data.originalFiles;
350
					//Ask for a refresh of the photowall
351
					Gallery.getFiles(Gallery.currentAlbum).done(function () {
352
						var fileId, path;
353
						// Removes the cached thumbnails of files which have been re-uploaded
354
						_(fileList).each(function (fileName) {
355
							path = Gallery.currentAlbum + '/' + fileName;
356
							if (Gallery.imageMap[path]) {
357
								fileId = Gallery.imageMap[path].fileId;
358
								if (Thumbnails.map[fileId]) {
359
									delete Thumbnails.map[fileId];
360
								}
361
							}
362
						});
363
364
						Gallery.view.init(Gallery.currentAlbum);
365
					});
366
				}
367
			});
368
369
			// Since Nextcloud 9.0
370
			if (OC.Uploader) {
371
				OC.Uploader.prototype._isReceivedSharedFile = function (file) {
372
					var path = file.name;
373
					var sharedWith = false;
374
375
					if (Gallery.currentAlbum !== '' && Gallery.currentAlbum !== '/') {
376
						path = Gallery.currentAlbum + '/' + path;
377
					}
378
					if (Gallery.imageMap[path] && Gallery.imageMap[path].sharedWithUser) {
379
						sharedWith = true;
380
					}
381
382
					return sharedWith;
383
				};
384
			}
385
		},
386
387
		/**
388
		 * Setups selection feature
389
		 * Also resets file actions list to be hidden in case of user navigating
390
		 * back and forth between albums
391
		 *
392
		 * @private
393
		 */
394
		_initSelection: function() {
395
			this._selectedFiles = {};
396
			this._filesConfig = new OC.Backbone.Model();
397
			this._selectionSummary = new OCA.Files.FileSummary(undefined, {config: this._filesConfig});
398
			if (!this.initialized) {
399
				this.element.on('change', '.selectCheckBox', _.bind(this._onClickFileCheckbox, this));
400
			}
401
402
			var selectedActionsList = $('#selectedActionsList');
403
			if (selectedActionsList && !selectedActionsList.hasClass('hidden')) {
404
				selectedActionsList.addClass('hidden');
405
			}
406
		},
407
408
		/**
409
		 * Adds all the click handlers to buttons the first time they appear in the interface
410
		 *
411
		 * @private
412
		 */
413
		_initButtons: function () {
414
			this.element.on("contextmenu", function(e) { e.preventDefault(); });
415
			$('#filelist-button').click(Gallery.switchToFilesView);
416
			$('#download').click(Gallery.download);
417
			$('#shared-button').click(Gallery.share);
418
			Gallery.infoBox = new Gallery.InfoBox();
419
			$('#album-info-button').click(Gallery.showInfo);
420
			$('#sort-name-button').click(Gallery.sorter);
421
			$('#sort-date-button').click(Gallery.sorter);
422
			$('#save #save-button').click(Gallery.showSaveForm);
423
			$('.save-form').submit(Gallery.saveForm);
424
			this._renderDownloadSelectedButton();
425
			this._renderNewButton();
426
			// Trigger cancelling of file upload
427
			$('#uploadprogresswrapper .stop').on('click', function () {
428
				OC.Upload.cancelUploads();
429
			});
430
			this.requestId = Math.random();
431
		},
432
433
		/**
434
		 * Sets up all the buttons of the interface and the breadcrumbs
435
		 *
436
		 * @param {string} albumPath
437
		 * @private
438
		 */
439
		_setupButtons: function (albumPath) {
440
			this._shareButtonSetup(albumPath);
441
			this._infoButtonSetup();
442
443
			var availableWidth = $(window).width() - Gallery.buttonsWidth;
444
			this.breadcrumb.init(albumPath, availableWidth);
445
			var album = Gallery.albumMap[albumPath];
446
447
			var sum = album.images.length + album.subAlbums.length;
448
			//If sum of the number of images and subalbums exceeds 1 then show the buttons.
449
			if(sum > 1)
450
			{
451
				$('#sort-name-button').show();
452
				$('#sort-date-button').show();
453
			}
454
			else
455
			{
456
				$('#sort-name-button').hide();
457
				$('#sort-date-button').hide();
458
			}
459
			var currentSort = Gallery.config.albumSorting;
460
			this.sortControlsSetup(currentSort.type, currentSort.order);
461
			Gallery.albumMap[Gallery.currentAlbum].images.sort(
462
				Gallery.utility.sortBy(currentSort.type,
463
					currentSort.order));
464
			Gallery.albumMap[Gallery.currentAlbum].subAlbums.sort(Gallery.utility.sortBy('name',
465
				currentSort.albumOrder));
466
467
			$('#save-button').show();
468
			$('#download').show();
469
			$('a.button.new').show();
470
		},
471
472
		/**
473
		 * Hide buttons in the controls bar
474
		 *
475
		 * @param uploadAllowed
476
		 */
477
		_hideButtons: function (uploadAllowed) {
478
			$('#album-info-button').hide();
479
			$('#shared-button').hide();
480
			$('#sort-name-button').hide();
481
			$('#sort-date-button').hide();
482
			$('#save-button').hide();
483
			$('#download').hide();
484
485
			if (!uploadAllowed) {
486
				$('a.button.new').hide();
487
			}
488
		},
489
490
		/**
491
		 * Shows or hides the share button depending on if we're in a public gallery or not
492
		 *
493
		 * @param {string} albumPath
494
		 * @private
495
		 */
496
		_shareButtonSetup: function (albumPath) {
497
			var shareButton = $('#shared-button');
498
			if (albumPath === '' || Gallery.token) {
499
				shareButton.hide();
500
			} else {
501
				shareButton.show();
502
			}
503
		},
504
505
		/**
506
		 * Shows or hides the info button based on the information we've received from the server
507
		 *
508
		 * @private
509
		 */
510
		_infoButtonSetup: function () {
511
			var infoButton = $('#album-info-button');
512
			infoButton.find('span').hide();
513
			var infoContentContainer = $('.album-info-container');
514
			infoContentContainer.slideUp();
515
			infoContentContainer.css('max-height',
516
				$(window).height() - Gallery.browserToolbarHeight);
517
			var albumInfo = Gallery.config.albumInfo;
518
			if (Gallery.config.albumError) {
519
				infoButton.hide();
520
				var text = '<strong>' + t('gallery', 'Configuration error') + '</strong></br>' +
521
					Gallery.config.albumError.message + '</br></br>';
522
				Gallery.utility.showHtmlNotification(text, 7);
523
			} else if ($.isEmptyObject(albumInfo)) {
524
				infoButton.hide();
525
			} else {
526
				infoButton.show();
527
				if (albumInfo.inherit !== 'yes' || albumInfo.level === 0) {
528
					infoButton.find('span').delay(1000).slideDown();
529
				}
530
			}
531
		},
532
533
		/**
534
		 * Sets the background colour of the photowall
535
		 *
536
		 * @private
537
		 */
538
		_setBackgroundColour: function () {
539
			var wrapper = $('#content-wrapper');
540
			var albumDesign = Gallery.config.albumDesign;
541
			if (!$.isEmptyObject(albumDesign) && albumDesign.background) {
542
				wrapper.css('background-color', albumDesign.background);
543
			} else {
544
				wrapper.css('background-color', '#fff');
545
			}
546
		},
547
548
		/**
549
		 * Picks the image which matches the sort order
550
		 *
551
		 * @param {string} sortType name or date
552
		 * @param {string} sortOrder asc or des
553
		 * @param {boolean} active determines if we're setting up the active sort button
554
		 * @private
555
		 */
556
		_setSortButton: function (sortType, sortOrder, active) {
557
			var button = $('#sort-' + sortType + '-button');
558
			// Removing all the classes which control the image in the button
559
			button.removeClass('active');
560
			button.find('img').removeClass('front');
561
			button.find('img').removeClass('back');
562
563
			// We need to determine the reverse order in order to send that image to the back
564
			var reverseSortOrder = 'des';
565
			if (sortOrder === 'des') {
566
				reverseSortOrder = 'asc';
567
			}
568
569
			// We assign the proper order to the button images
570
			button.find('img.' + sortOrder).addClass('front');
571
			button.find('img.' + reverseSortOrder).addClass('back');
572
573
			// The active button needs a hover action for the flip effect
574
			if (active) {
575
				button.addClass('active');
576
				if (button.is(":hover")) {
577
					button.removeClass('hover');
578
				}
579
				// We can't use a toggle here
580
				button.hover(function () {
581
						$(this).addClass('hover');
582
					},
583
					function () {
584
						$(this).removeClass('hover');
585
					});
586
			}
587
		},
588
589
		/**
590
		 * If no url is entered then do not show the error box.
591
		 *
592
		 */
593
		_blankUrl: function() {
594
			$('#remote_address').on("change keyup paste", function() {
595
 				if ($(this).val() === '') {
596
 					$('#save-button-confirm').prop('disabled', true);
597
 				} else {
598
 					$('#save-button-confirm').prop('disabled', false);
599
 				}
600
			});
601
		},
602
603
		/**
604
		 * Creates the [+] button allowing users who can't drag and drop to upload files
605
		 *
606
		 * @see core/apps/files/js/filelist.js
607
		 * @private
608
		 */
609
		_renderNewButton: function () {
610
			// if no actions container exist, skip
611
			var $actionsContainer = $('.actions.creatable');
612
			if (!$actionsContainer.length) {
613
				return;
614
			}
615
			if (!this._addButtonTemplate) {
616
				this._addButtonTemplate = Handlebars.compile(TEMPLATE_ADDBUTTON);
617
			}
618
			var $newButton = $(this._addButtonTemplate({
619
				addText: t('gallery', 'New'),
620
				iconUrl: OC.imagePath('core', 'actions/add')
621
			}));
622
623
			$actionsContainer.prepend($newButton);
624
			$newButton.tooltip({'placement': 'bottom'});
625
626
			$newButton.click(_.bind(this._onClickNewButton, this));
627
			this._newButton = $newButton;
628
		},
629
630
		/**
631
		 * Creates the click handler for the [+] button
632
		 * @param event
633
		 * @returns {boolean}
634
		 *
635
		 * @see core/apps/files/js/filelist.js
636
		 * @private
637
		 */
638
		_onClickNewButton: function (event) {
639
			var $target = $(event.target);
640
			if (!$target.hasClass('.button')) {
641
				$target = $target.closest('.button');
642
			}
643
			this._newButton.tooltip('hide');
644
			event.preventDefault();
645
			if ($target.hasClass('disabled')) {
646
				return false;
647
			}
648
			if (!this._newFileMenu) {
649
				this._newFileMenu = new Gallery.NewFileMenu();
650
				$('.actions').append(this._newFileMenu.$el);
651
			}
652
			this._newFileMenu.showAt($target);
653
654
			if (Gallery.currentAlbum === '') {
655
				$('.menuitem[data-action="hideAlbum"]').parent().hide();
656
			}
657
			return false;
658
		},
659
660
		/**
661
		 * Creates the download individual files button
662
		 *
663
		 * @see core/apps/files/js/filelist.js
664
		 * @private
665
		 */
666
		_renderDownloadSelectedButton: function () {
667
			var $actionsContainer = $('#controls .right');
668
			if (!this._downloadButtonTemplate) {
669
				this._downloadButtonTemplate = Handlebars.compile(TEMPLATE_DOWNLOADBUTTON);
670
			}
671
			var $downloadButton = $(this._downloadButtonTemplate({
672
				addText: t('gallery', 'Download'),
673
				iconUrl: OC.imagePath('core', 'actions/download')
674
			}));
675
676
			$actionsContainer.prepend($downloadButton);
677
			$downloadButton.tooltip({'placement': 'bottom'});
678
679
			$downloadButton.click(_.bind(this._onClickDownloadSelected, this));
680
		},
681
682
		/**
683
		 * Event handler for when clicking on "Download" for the selected files
684
		 *
685
		 * @see core/apps/files/js/filelist.js
686
		 * @private
687
		 */
688
		_onClickDownloadSelected: function(event) {
689
			var files;
690
			var dir = Gallery.currentAlbum;
691
			if (dir === '') {
692
				dir = '/';
693
			}
694
			files = _.pluck(this.getSelectedFiles(), 'path');
695
			files.forEach(function(file, index, files) {
696
				files[index] = OC.basename(file);
697
			});
698
699
			var downloadFileaction = $('#selectedActionsList').find('.download');
700
701
			// don't allow a second click on the download action
702
			if(downloadFileaction.hasClass('disabled')) {
703
				event.preventDefault();
704
				return;
705
			}
706
707
			var disableLoadingState = function(){
708
				OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, false);
709
			};
710
711
			OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, true);
712
			if(this.getSelectedFiles().length > 1) {
713
				OCA.Files.Files.handleDownload(Gallery.getSelectionDownloadUrl(files, dir, true), disableLoadingState);
714
			}
715
			else {
716
				var first = OC.basename(this.getSelectedFiles()[0].path);
717
				OCA.Files.Files.handleDownload(Gallery.getSelectionDownloadUrl(first, dir, true), disableLoadingState);
718
			}
719
			return false;
720
	},
721
722
		/**
723
		 * Returns the file info of the selected files
724
		 *
725
		 * @return array of file names
726
		 *
727
		 * @see core/apps/files/js/filelist.js
728
		 * @private
729
		 */
730
		getSelectedFiles: function() {
731
			return _.values(this._selectedFiles);
732
		},
733
734
		/**
735
		 * Returns the file data from a given file element.
736
		 * @param $el file tr element
737
		 * @return file data
738
		 *
739
		 * @see core/apps/files/js/filelist.js
740
		 * @private
741
		 */
742
		elementToFile: function($el){
743
			$el = $($el);
744
			var data = {
745
				id: parseInt($el.attr('data-id'), 10),
746
			};
747
			var path = $el.attr('data-path');
748
			if (path) {
749
				data.path = path;
750
			}
751
			return data;
752
		},
753
754
		/**
755
		 * Selected/deselects the given file element and updated
756
		 * the internal selection cache.
757
		 *
758
		 * @param {Object} $element single image
759
		 * @param {bool} state true to select, false to deselect
760
		 *
761
		 * @see core/apps/files/js/filelist.js
762
		 * @private
763
		 */
764
		_selectFileEl: function($element, state, showDetailsView) {
0 ignored issues
show
Unused Code introduced by
The parameter showDetailsView is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
showDetailsView does not seem to be used.
Loading history...
765
			var $checkbox = $element.find('row-element>.image-label>.selectCheckBox');
766
			var oldData = !!this._selectedFiles[$element.data('id')];
767
			var data;
768
			$checkbox.prop('checked', state);
769
			$element.toggleClass('selected', state);
770
			// already selected ?
771
			if (state === oldData) {
772
				return;
773
			}
774
			data = this.elementToFile($element);
775
			if (state) {
776
				this._selectedFiles[$element.data('id')] = data;
777
				this._selectionSummary.add(data);
778
			}
779
			else {
780
				delete this._selectedFiles[$element.data('id')];
781
				this._selectionSummary.remove(data);
782
			}
783
		},
784
785
		/**
786
		 * Event handler for when clicking on a element's checkbox
787
		 *
788
		 * @see core/apps/files/js/filelist.js
789
		 * @private
790
		 */
791
		_onClickFileCheckbox: function(event) {
792
			var $image = $(event.target).closest('.' + GalleryImage.cssClass);
0 ignored issues
show
Bug introduced by
The variable GalleryImage seems to be never declared. If this is a global, consider adding a /** global: GalleryImage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
GalleryImage does not seem to be defined.
Loading history...
793
			var state = !$image.hasClass('selected');
794
			this._selectFileEl($image, state);
795
			this._lastChecked = $image;
796
			this.updateSelectionSummary();
797
		},
798
799
		/**
800
		 * Update UI based on the current selection
801
		 *
802
		 * @see core/apps/files/js/filelist.js
803
		 * @private
804
		 */
805
		updateSelectionSummary: function() {
806
			var summary = this._selectionSummary.summary;
807
			var selection;
0 ignored issues
show
Unused Code introduced by
The variable selection seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
selection does not seem to be used.
Loading history...
808
809
			if (summary.totalFiles === 0 && summary.totalDirs === 0) {
810
				$('#selectedActionsList').addClass('hidden');
811
			}
812
			else {
813
				$('#selectedActionsList').removeClass('hidden');
814
			}
815
		},
816
817
	};
818
819
	Gallery.View = View;
820
})(jQuery, _, OC, t, Gallery);
821